-- Copyright (c) 2011-2012 Casey Baxter
-- See LICENSE file for details

---------------------------------------------------------------------------------------------------
-- -= Object =-
---------------------------------------------------------------------------------------------------
-- Setup
local Object = {class = "Object"}
Object.__index = Object

---------------------------------------------------------------------------------------------------

-- Returns a new Object
function Object.init(o)
    local obj = setmetatable(o, Object)
    obj.drawInfo = {
    
        -- x and y are the drawing location of the object. This is different than the object's x and
        -- y value which is the object's placement on the map.
        x = 0,      -- The x draw location
        y = 0,      -- The y draw location
        
        -- These limit the drawing of the object. If the object falls out of the bounds of
        -- the map's drawRange then the object will not be drawn. 
        left = 0,   -- The leftmost point on the object
        right = 0,  -- The rightmost point on the object
        top = 0,    -- The highest point on the object
        bottom = 0, -- The lowest point on the object
        
        -- The order to draw the object in relation to other objects. Usually equal to bottom.
        order = 0,
        
        -- In addition to this, other drawing information can be stored in the numerical 
        -- indicies which is context sensitive to the map's orientation, if the object has a gid, or
        -- of the object is a polygon or polyline object.
    } 
    
    -- Update the draw info
    Object.updateDrawInfo(obj)
    
    -- Return our object
    return obj
end

---------------------------------------------------------------------------------------------------
-- Updates the draw information. Call this every time the object moves or changes size.
function Object:updateDrawInfo()
	local di = self.drawInfo
	local map = self.layer.map
	local verts = self.polygon or self.polyline
	local iso = map.orientation == "isometric"
	local ox, oy, x, y = map.offsetX, map.offsetY, self.x, self.y
	
	if verts then
		self.drawInfo = {}
		di = self.drawInfo
		if iso then
			for k = 1, #verts, 2 do
				di[k], di[k + 1] = map:fromIso(x + verts[k], y + verts[k + 1])
				di[k], di[k + 1] = di[k] - ox, di[k + 1] - oy
			end
		else
			for k = 1, #verts, 2 do
				di[k], di[k + 1] = x + verts[k] - ox, y + verts[k+1] - oy
			end
		end
		di.x, di.y = di[1], di[2]
		di.left, di.right, di.top, di.bottom = di.x, di.x, di.y, di.y
		for k = 1, #di, 2 do
			x, y = di[k], di[k + 1]
			if x < di.left   then di.left   = x end
			if x > di.right  then di.right  = x end
			if y < di.top    then di.top    = y end
			if y > di.bottom then di.bottom = y end
		end
		di.order = di.bottom
	
	elseif self.gid then
		local t = map.tiles[self.gid]
		if iso then
			di.x, di.y = map:fromIso(x, y)
			di.x, di.y = di.x - ox, di.y - oy
			di.x = di.x - map.tileWidth / 2
		else
			di.x, di.y = x - ox, y - oy
		end
		di.order = di.y
		di.left, di.right = di.x, di.x + t.width
		di.top, di.bottom = di.y, di.y + t.height
	
	elseif iso then
		di[1], di[2] = map:fromIso(x, y)
		di[3], di[4] = map:fromIso(x + self.width, y)
		di[5], di[6] = map:fromIso(x + self.width, y + self.height)
		di[7], di[8] = map:fromIso(x, y + self.height)
		for i =1, 7, 2 do
			di[i], di[i + 1] = di[i] - ox, di[i + 1] - oy
		end
		di.left, di.right, di.top, di.bottom = di[7], di[3], di[2], di[6]
		di.order = 1
	
	else
		di.x, di.y = x - ox, y - oy
		di[1], di[2] = di.x, di.y
		di[3], di[4] = self.width, self.height
		di.left, di.top, di.right, di.bottom = di.x, di.y , di.x + di[3], di.y + di[4]
		di.order = 1
	end
end

---------------------------------------------------------------------------------------------------
-- Draw the object. The passed color is the color of the object layer the object belongs to.
function Object:draw(x, y, r, g, b, a)
	if not self.visible then return end

	local di = self.drawInfo
	love.graphics.setLineWidth(1)

	if self.text then
		love.graphics.setColor(r, g, b, a)
		love.graphics.print(self.text, di[1], di[2])
	
	elseif self.ellipse then
		local rx, ry = di[3] / 2, di[4] / 2
		local cx, cy = di[1] + rx, di[2] + ry
		love.graphics.setColor(r, g, b, a / 4)
		love.graphics.ellipse("fill", cx, cy, rx, ry)
		love.graphics.setColor(r, g, b, a)
		love.graphics.ellipse("line", cx, cy, rx, ry)
	
	elseif self.point then
		love.graphics.setColor(r, g, b, a)
		love.graphics.circle("fill", di[1], di[2], 2)
	
	-- The object is a polyline.
	elseif self.polyline then
		love.graphics.setColor(r, g, b, a)
		love.graphics.line(di)
	
	-- The object is a polygon.
	elseif self.polygon then
		love.graphics.setColor(r, g, b, a / 4)
		love.graphics.polygon( "fill", di) 
		love.graphics.setColor(r, g, b, a)
		love.graphics.polygon( "line", di) 
	
	-- The object is a tile object. Draw the tile.
	elseif self.gid then
		love.graphics.setColor(1,1,1,a)
		local tile = self.layer.map.tiles[self.gid]
		tile:draw(di.x, di.y - self.height, 0 , self.width / tile.width, self.height / tile.height)
		
	-- Map is isometric. Draw a parallelogram.
	elseif self.layer.map.orientation == "isometric" then
		love.graphics.setColor(r, g, b, a / 4)
		love.graphics.polygon("fill", di)
		love.graphics.setColor(r,g,b,a)
		love.graphics.polygon("line", di)

	-- Map is orthogonal. Draw a rectangle.
	else
		local rx,ry,rw,rh = unpack(di)
		love.graphics.setColor(r, g, b, a / 4)
		love.graphics.rectangle("fill", rx,ry,rw,rh)
		love.graphics.setColor(r, g, b, a)
		love.graphics.rectangle("line", rx,ry,rw,rh)
    end
end

---------------------------------------------------------------------------------------------------
-- Returns the Object class
return Object
